﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
using SCRUM.Core.BusinessObjects;

/// <summary>
/// Widget for manipulation with entities of itemType
/// Contains filter, datagrid and hierarchical object details for maipulation with data
/// </summary>
public abstract class DataOverviewWidgetWithDetails<itemType, superiorItemType> : DataOverviewWidget<itemType> 
    //where detailsType : HierarchicalObjectDetails<itemType,superiorItemType>
    where itemType : HierarchicalBusinessObject
{
    /// <summary>
    /// Refreshes whole state of the widget.
    /// </summary>
    public override void RefreshWidget()
    {
        base.RefreshWidget();
        bool itemSelected = this.data.SelectedIndex != -1;
        SelectAndDisplayItem(this.selectedItem, this.filtersSuperiorItemID, itemSelected, this.filtersProjectID);
        //this.buttonCreate.Visible = this.filtersSuperiorItemID != -1 && this.UserRights.CanModify;
        this.buttonCreate.Visible = this.filtersSuperiorItemID != -1;
    }

    /// <summary>
    /// Sets visibility of detail of item and buttons to create, edit, delete and cancel in form
    /// </summary>
    /// <param name="item">Type of item to dislay</param>
    /// <param name="superiorItemID">Parent item ID</param>
    /// <param name="show">If detail should be displayed</param>
    /// <param name="projectID">Belongs to project with this ID</param>
    protected virtual void SelectAndDisplayItem(itemType item, int superiorItemID, bool show, int projectID)
    {
        bool exists = item != null;
        this.itemDetails.ProjectID = projectID;
        this.itemDetails.SuperiorItemID = exists ? item.SuperiorItemID : superiorItemID;
        this.itemDetails.SelectedItem = item;
        this.itemDetails.Visible = show;
        //this.buttonCreateItem.Visible = show && !exists && this.UserRights.CanModify;
        //this.buttonSaveItem.Visible = show && exists && this.UserRights.CanModify;
        //this.buttonDeleteItem.Visible = show && exists && this.UserRights.CanModify;
        this.buttonCreateItem.Visible = show && !exists;
        this.buttonSaveItem.Visible = show && exists;
        this.buttonDeleteItem.Visible = show && exists;
        this.buttonCancelItem.Visible = show;
    }

    #region [ FILTER ]
    /// <summary>
    /// Sets common attributes (visibility, index,..) for both changes
    /// </summary>
    protected void DropDownList_SelectedIndexChanded(object sender, EventArgs e)
    {
        HideDetails();
    }
    #endregion

    #region [ ITEM CONTROLS ]

    /// <summary>
    /// When user tries to create new item
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void ButtonCreate_Click(object sender, EventArgs e)
    {
        SelectAndDisplayItem(null, filtersSuperiorItemID, true, -1);
    }

    /// <summary>
    /// User tries to create new Sprint
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void ButtonCreateItem_Click(object sender, EventArgs e)
    {
        try
        {
            CreateItem();
            HideDetails();
        }
        catch (SCRUM.Core.Exceptions.Database.InconsistentDatabaseException ex)
        {
            ShowOperationResult(MessageType.Error, ex.Message);
        }
    }

    /// <summary>
    /// User tries to save selected (potentialy modified) sprint
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void ButtonSaveItem_Click(object sender, EventArgs e)
    {
        try
        {
            SaveItem();
            HideDetails();
        }
        catch (SCRUM.Core.Exceptions.Database.InconsistentDatabaseException ex)
        {
            ShowOperationResult(MessageType.Error, ex.Message);
        }
    }

    /// <summary>
    /// User tries to cancel updating/creating of sprint
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void ButtonCancelItem_Click(object sender, EventArgs e)
    {
        HideDetails();
    }

    /// <summary>
    /// User tries to delete item
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void ButtonDeleteItem_Click(object sender, EventArgs e)
    {
        DeleteItem_Click(selectedItem.ID);
    }

    /// <summary>
    /// Deletes selected entity
    /// </summary>
    /// <param name="sender">sender</param>
    /// <param name="ce">The <see cref="System.Web.UI.WebControls.CommandEventArgs"/> instance containing the event data.</param>
    protected void ImageButtonDeleteItem_Click(object sender, CommandEventArgs ce)
    {
        DeleteItem_Click(Int32.Parse((string)ce.CommandArgument));
    }

    /// <summary>
    /// Deletes selected item specified by ID
    /// </summary>
    /// <param name="itemID">ID of item to delete</param>
    protected void DeleteItem_Click(int itemID)
    {
        try
        {
            DeleteItem(itemID);
            HideDetails();
        }
        catch (SCRUM.Core.Exceptions.Database.InconsistentDatabaseException ex)
        {
            ShowOperationResult(MessageType.Error, ex.Message);
        }
    }

    protected virtual void CreateItem() { throw new NotSupportedException("spravit abstract"); }
    
    protected virtual void SaveItem() { throw new NotSupportedException("spravit abstract"); }

    protected virtual void DeleteItem(int itemID) { throw new NotSupportedException("spravit abstract"); }

    /// <summary>
    /// Hides all item's details and refreshes widget
    /// </summary>
    protected void HideDetails()
    {
        data.SelectedIndex = -1;
        RefreshWidget();
    }

    #endregion

    #region [ READONLY ]

    /// <summary>
    /// Holds information about read/write priviledges
    /// </summary>
    public override bool ReadOnly
    {
        set
        {
            this.itemDetails.ReadOnly = value;
            base.ReadOnly = value;
        }
    }

    /// <summary>
    /// Pre rendering of page
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void Page_PreRender(object sender, EventArgs e)
    {
        HandleReadOnlyMode(this.ReadOnly);
    }

    /// <summary>
    /// Sets read only mode on buttons
    /// </summary>
    /// <param name="readonly_">If mode is read only</param>
    private void HandleReadOnlyMode(bool readonly_)
    {
        if (readonly_)
        {
            this.buttonCreate.Visible = false;
            this.buttonCreateItem.Visible = false;
            this.buttonSaveItem.Visible = false;
            this.buttonDeleteItem.Visible = false;
        }
    }

    #endregion
    
    /// <summary>
    /// Specifies instance of button that shows new item creation form
    /// </summary>
    protected abstract Button buttonCreate { get; }

    /// <summary>
    /// Specifies instance of button that creates new item 
    /// </summary>
    protected abstract Button buttonCreateItem { get; }

    /// <summary>
    /// Specifies instance of button that saves edited values of item
    /// </summary>
    protected abstract Button buttonSaveItem { get; }

    /// <summary>
    /// Specifies instance of button that deletes item
    /// </summary>
    protected abstract Button buttonDeleteItem { get; }

    /// <summary>
    /// Specifies instance of button that hides details of item
    /// </summary>
    protected abstract Button buttonCancelItem { get; }

    /// <summary>
    /// Available items displayed in datagrid
    /// </summary>
    protected abstract HierarchicalObjectDetails<itemType,superiorItemType> itemDetails { get; }

    /// <summary>
    /// Filterred parent entity ID
    /// </summary>
    protected abstract int filtersSuperiorItemID { get; }

    /// <summary>
    /// Project that item belongs to
    /// </summary>
    protected abstract int filtersProjectID { get; }
    
}
